#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##-- G23 -- S07 ------------------------------------------------------------##
__all__ = []

from .. import pilelib as stack
from .. import formlib as layout
from ..forms import (fortythieves as FortyThievesLayout,
                     freecell as FreeCellLayout,)
from ..gamelib import info as gi, game
from ..hint import DefaultHint, CautiousDefaultHint
from ..packlib import info as cs, place
from ..piles import spider
from ..utillib.misc import kwdefault

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class DropAC_RowStack(spider.DropMethods, stack.SuperMoveAC_RowStack):

    def cardsPlay(self, cards):
        """
        cardsBuild(from_stack:obj, cards:seq) -> bool

        Check parent.cardsBuild() and seq has enough plays build individual.

        :param object from_stack: sending pile
        :param sequence cards: cards from sending pile
        :return: pile accepts ``cards``?
        :rtype: boolean
        """
        return ((len(cards) == 13 and self._sequence(cards)) or
                super(DropAC_RowStack, self).cardsPlay(cards))


class ShadeAC_RowStack(stack.SuperMoveAC_RowStack):
    _BOTTOM_IMAGE_ = 'shade'


class SequenceReserve(stack.ReserveStack):

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack:obj, cards:seq) -> bool

        Check if pile can build with cards from from_stack. Addition pile
        may build with any _row_ seq while gap.

        :param object from_stack: sending pile
        :param sequence cards: cards from sending pile
        :return: pile accepts ``cards``?
        :rtype: boolean
        """
        return (not self.cards and
                super(SequenceReserve).cardsBuild(from_stack, cards))


class SuitReserve(stack.ReserveStack):
    _BOTTOM_IMAGE_ = 'suit'


class FreeCell(game.Game):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card. Build down in rank by alt color. Play top or seq if
      possible as super move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=8, name='FreeCell', game_type=(GT.FREECELL | GT.OPEN |
                    GT.POPULAR | GT.GNOME | GT.KDE | GT.XPAT), decks=1,
                    skill_level=SL.SKILL, version='1.02')
    __author__ = 'Markus Oberhumer'
    __credits__ = ['Paul Alfille']
    __version__ = 7.70

    _layout_ = FreeCellLayout.FreeCellLayout
    _talon_ = stack.InitialDealTalon
    _foundation_ = stack.SS_Foundation
    _row_ = stack.SuperMoveAC_RowStack
    _reserve_ = stack.ReserveStack
    _hint_ = CautiousDefaultHint

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, reserves=4, texts=False)
        return super(FreeCell, self)._create_game(**kw), self.s

    def _start(self, rows=7, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~7 ea.

        .. \_start(rows=7) -> None
        """
        for i in range(rows - 2):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()
        self.s['talon'].dealRowAvail()


class RelaxedFreeCell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6, 6, 6,] open card. Build down in rank by alt
      color. Play seq.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=5, name='Relaxed FreeCell', game_type=(GT.FREECELL |
                    GT.RELAXED | GT.OPEN), decks=1, version='1.01',
                    skill_level=SL.SKILL, altnames=('FreeCell (Relaxed)',))
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = stack.AC_RowStack


class ForeCell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [6 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal 6 open card. Build
      down in rank by alt color. Play top or seq if possible as super move.
      Base KING.

    _reserve_
      Init deal 1 card. Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Layout _layout_: layout.FreeCellLayout
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=46, name='ForeCell', game_type=(GT.FREECELL | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = Wrap(stack.SuperMoveAC_RowStack, base_rank=cs.KING)

    def _start(self, rows=6, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~6 ea.
          - s[reserves] 1 ea.

        .. \_start(rows=6) -> None
        """
        super(ForeCell, self)._start(rows=6, **kw)
        self.s['talon'].dealRow(rows=self.s['reserves'])


class ChallengeFreeCell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card with 1st card ACE and 2nd card TWO. Build down in rank
      by alt color. Play top or seq if possible as super move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Layout _layout_: layout.FreeCellLayout
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=336, name='Challenge FreeCell', game_type=(GT.FREECELL
                    | GT.OPEN), decks=1, skill_level=SL.SKILL,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __credits__ = ['Thomas Warfield']
    __version__ = 7.70

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE for _foundation_ deal and TWO for _row_ deal on
        top by rank, suit, deck .
        """
        return place.MoveToTop(cards, place.AllAceTwo)


class SuperChallengeFreeCell(ChallengeFreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card with 1st card ACE and 2nd card TWO. Build down in rank
      by alt color. Play top or seq if possible as super move. Base KING

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=337, name='Super Challenge FreeCell',
                    game_type=(GT.FREECELL | GT.OPEN), decks=1,
                    skill_level=SL.SKILL, version='0.90fc')
    __author__ = 'Skomoroh'
    __credits__ = ['Thomas Warfield']
    __version__ = 7.70

    _row_ = Wrap(stack.SuperMoveAC_RowStack, base_rank=cs.KING)


class Spidercells(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card. Build down in rank by alt color. Play top or seq if
      possible as super move. Drop full seq on _foundation_.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build none. Play none.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=363, name='Spidercells', game_type=(GT.SPIDER |
                    GT.OPEN), decks=1, skill_level=SL.MOSTLY_SKILL,
                    version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = spider.AC_Foundation
    _row_ = DropAC_RowStack


class KingCell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card. Build down in rank by alt color. Play top or seq if
      possible as super move. Base KING.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=542, name='KingCell', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(stack.SuperMoveRK_RowStack, base_rank=cs.KING)


class Bath(KingCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [10 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal [1, 2, 3, 4, 5, 6, 7, 8, 8, 8] open card. Build down in rank by
      alt color. Play top or seq if possible as super move. Base KING.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=383, name='Bath', game_type=(GT.FREECELL | GT.OPEN),
                    decks=1, skill_level=SL.SKILL,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, reserves=2)
        return super(Bath, self)._create_game(**kw)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 1..LEN-1 up.
          - s[rows][7:] 2 ea up.

        .. \_start([]) -> None
        """
        for i in range(len(self.s['rows'] - 2)):
            self.s['talon'].dealRow(rows=self.s['rows'][i:], frames=0)
        self.s['talon'].dealRow(rows=self.s['rows'][7:])
        self.s['talon'].dealRow(rows=self.s['rows'][7:])


class Stalactites(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal 6 open card. Build
      none. Play top.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Init deal any base for all. Build up in rank alone wrap from
      base. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=77, name='Stalactites', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1,
                    skill_level=SL.MOSTLY_SKILL, altnames=('Grampus',
                    'Old Mole'), version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _foundation_ = Wrap(stack.RK_Foundation, mod=13, min_cards=1)
    _row_ = stack.BasicRowStack

    def _create_game(self, **kw):
        kw.setdefault('reserves', 2)
        super(Stalactites, self)._create_game(**kw)

    def _start(self, rows=6, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~7 ea.
          - s[foundations] 1 ea. save all caps.

        .. \_start(rows=6) -> None
        """
        super(Stalactites, self)._start(rows=rows, **kw)
        self.s['talon'].dealRow(rows=self.s['foundations'])
        for s in self.s['foundations']:
            self._save_stack_caps(s, base_rank=s.BASECARD['rank'])


class DoubleFreecell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [10 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [6 horz NW, no offset]
    _row_
      Init deal 10 open card. Build
      down in rank by alt color. Play top or seq if possible as super move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Init deal base ACE. Build up in rank by same suit wrap. Play
      top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=264, name='Double FreeCell', game_type=(GT.FREECELL |
                    GT.OPEN), decks=2, version='0.80fc',
                    skill_level=SL.MOSTLY_SKILL)
    __author__ = 'Skomoroh'
    __credits__ = ['Thomas Warfield']
    __version__ = 7.70

    _foundation_ = Wrap(stack.SS_Foundation, mod=13,
                                max_cards=26)

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, reserves=6, playcard=16, ndecks=1,
                  bases=range(4))
        return super(DoubleFreecell, self)._create_game(**kw)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE of suit on bottom by suit, deck for
        _foundation_ deal.
        """
        return place.MoveToBottom(cards, place.OneAce)

    def _start(self, rows=10, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~10 ea.
          - s[foundations] 1 ea.

        .. \_start(rows=10) -> None
        """
        super(DoubleFreecell, self)._start(rows=rows, **kw)
        self.s['talon'].dealRow(rows=self.s['foundations'])


class TripleFreecell(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.fortythieves.FortyThievesLayout
        - reserve [10 horz S foundation, no offset]
        - row [13 horz S reserve, vert offset]
        - talon [1 SE, no offset]
        - waste [1 W talon, no offset]
        - foundation [12 horz NE, no offset]

    _row_
      Init deal 12 open card. Build down in rank by
      alt color. Play top or seq if possible as super move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Layout _layout_: layout.FortyThievesLayout
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=265, name='Triple FreeCell', game_type=(GT.FREECELL |
                    GT.OPEN), decks=3, skill_level=SL.MOSTLY_SKILL,
                    altnames=('FreeCell (3 Decks, 10 Cells)',),
                    version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FortyThievesLayout.FortyThievesLayout

    def _create_game(self, **kw):
        kwdefault(kw, rows=13, reserves=10, playcard=20, align='sw')
        return super(TripleFreecell, self)._create_game(**kw)

    def _start(self, rows=12, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~12 ea.

        .. \_start(rows=12) -> None
        """
        super(TripleFreecell, self)._start(rows=rows, **kw)


class Cell11(TripleFreecell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.fortythieves.FortyThievesLayout
        - row [13 horz S reserve, vert offset]
        - talon [1 SE, no offset]
        - foundation [12 horz N, no offset]
        - reserve [11 horz S foundation, no offset]

    _row_
      Init deal [11, 12, 12, 12, 12, 12, 12, 12, 12,
      12, 12, 12, 11] open card. Build down in rank by alt color. Play top or
      seq if possible  as super move.

    _reserve_
      Init deal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
      card. Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=451, name='Cell 11', game_type=(GT.FREECELL | GT.OPEN),
                    decks=3, skill_level=SL.MOSTLY_SKILL,
                    version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FortyThievesLayout.FortyThievesLayout

    def _create_game(self, **kw):
        kwdefault(kw, rows=12, reserves=11)
        return super(Cell11, self)._create_game(**kw)

    def _start(self, rows=11, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~11 ea up.
          - s['rows'][1:-1] 1 ea.
          - s['reserves'][::10] 1 ea.

        .. \_start(rows=11) -> None
        """
        return super(Cell11, self)._start(rows=rows, **kw)
        self.s['talon'].dealRow(rows=self.s['rows'][1:-1])
        self.s['talon'].dealRow(rows=self.s['reserves'][::10])


class BigCell(TripleFreecell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.fortythieves.FortyThievesLayout
        - row [13 horz S reserve, vert offset]
        - talon [1 SE, no offset]
        - foundation [12 horz N, no offset]
        - reserve [4 horz S foundation, no offset]

    _row_
      Init deal 12 open card. Build down in rank by
      alt color. Play top or seq if possible as super move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=509, name='Big Cell', game_type=(GT.FREECELL | GT.OPEN
                    | GT.ORIGINAL), decks=3,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc',
                     altnames=('FreeCell (3 Decks, 4 Cells)',))
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FortyThievesLayout.FortyThievesLayout
    _row_ = stack.SuperMoveAC_RowStack

    def _create_game(self, **kw):
        kwdefault(kw, rows=13, reserves=4)
        return super(BigCell, self)._create_game(**kw)


class SevenByFour(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [7 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [8, 8, 8, 7, 7, 7, 7] open card.
      Build down in rank by alt color. Play top or seq if possible as super
      move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: AC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=364, name='Seven by Four', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1, skill_level=SL.SKILL,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 7)
        return super(SevenByFour, self)._create_game(**kw)

    def _start(self, rows=8, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~8 ea.

        .. \_start(rows=8) -> None
        """
        return super(SevenByFour, self)._start(rows=rows, **kw)


class SevenByFive(SevenByFour):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [7 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [5 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [8, 8, 8, 7, 7, 7, 7] open card.
      Build down in rank by alt color. Play top or seq if possible as super
      move.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: AC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=365, name='Seven by Five', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1, skill_level=SL.SKILL,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('reserves', 5)
        return super(SevenByFive, self)._create_game(**kw)


class Clink(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [2 horz NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal 6 open card. Build
      down in rank by alt color. Play top or seq if possible as super move.

    _reserve_
      Init deal 1 card. Build any 1 card. Play top.

    _foundation_
      Init deal base ACE clubs spades. Build up in rank by alt
      color wrap. Play none.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.AC_Foundation (max_cards=26, mod=13,
      max_move=0)
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=394, name='Clink', game_type=(GT.FREECELL | GT.OPEN
                    | GT.ORIGINAL), decks=1, version='0.90fc',
                    skill_level=SL.MOSTLY_SKILL)
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = Wrap(stack.AC_Foundation, max_cards=26,
                                mod=13, max_move=0)

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, reserves=2, texts=False, bases=range(2))
        return super(Clink, self)._create_game(**kw)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return black ACE of suit on bottom by suit, deck for
        _foundation_ deal.
        """
        return place.MoveToBottom(cards, lambda c: place.OneAce(c,
                                                                suits=[0, 2]))

    def _start(self, rows=6, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~6 ea up.
          - s[reserves] 1 ea.
          - s[foundations] 1 ea.

        .. \_start(rows=6) -> None
        """
        super(Clink, self)._start(rows=rows, **kw)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow(rows=self.s['foundations'])


class Repair(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Pile 10 horz S _reserve_ and _foundation_. Init deal [7, 7, 7, 7, 6, 6,
      6, 6,] open card. Build down in rank by alt color. Play top or seq if
      possible via _reserve_ play.

    _reserve_
      Pile 4 horz NW. Init deal 1 card. Build any 1 card. Play top.

    _foundation_
      Pile 8 over 2 rows NE. Build up in rank by alt color. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=448, name='Repair', game_type=(GT.FREECELL | GT.OPEN),
                    decks=2, skill_level=SL.MOSTLY_SKILL,
                    version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = stack.SuperMoveAC_RowStack

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, reserves=4, playcards=26)
        super(Repair, self)._create_game(**kw)

    def _start(self, rows=10, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~10 ea up.
          - s[reserves] 1 ea.

        .. \_start(rows=10) -> None
        """
        super(Clink, self)._start(rows=rows, **kw)
        self.s['talon'].dealRow(rows=self.s['reserves'])


class FourColours(SevenByFour):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [7 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [13, 13, 13, 13, 0, 0, 0] open card
      with each pile 1 suit. Build down in rank by alt color. Play top or seq
      if possible via _reserve_ play.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SuperMoveAC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=464, name='Four Colours', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1, skill_level=SL.MOSTLY_SKILL,
                    version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = ShadeAC_RowStack

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~4 ea. suit per.

        .. \_start() -> None
        """
        for i in range(40):
            self.s['talon'].dealrow(
                         rows=[self.s['rows'][self.s['talon'].TOPCARD['suit']]],
                         frames=0)
        while talon.cards:
            self.s['talon'].dealrow(
                         rows=[self.s['rows'][self.s['talon'].TOPCARD['suit']]])


class GermanFreeCell(SevenByFour):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [7 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [4 horz NW, no offset]

    _row_
      Init deal [8, 8, 8, 7, 7, 7, 7] open card.
      Build down in rank by alt color. Play top or seq if possible via
      _reserve_ play.

    _reserve_
      Build any 1 card of 1 suit. Play top. Base [clubs,\
      hearts, spades, diamonds]

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: AC_RowStack
    :cvar Stack _reserve_: SuitReserve
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=520, name='German FreeCell', game_type=(GT.FREECELL |
                    GT.OPEN), decks=1, skill_level=SL.SKILL,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = stack.AC_RowStack
    _reserve_ = SuitReserve

    def _create_game(self, **kw):
        l, s = super(GermanFreeCell, self)._create_game(**kw)
        for suit, stack in zip(l.SUITS, s['reserves']):
            stack.cap['base_suit'] = suit


class OceanTowers(TripleFreecell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.fortythieves.FortyThievesLayout
        - row [14 horz S reserve, vert offset]
        - talon [1 SE, no offset]
        - foundation [8 horz N, no offset]
        - reserve [8 horz S foundation, no offset]

    _row_
      Pile 14 horz S _reserve_. Init deal 7 open card. Build down in rank by
      same suit. Play top or seq if possible via _reserve_ play. Base KING.

    _reserve_
      Pile 8 horz S _foundation_. Init deal [0, 1, 1, 1, 1, 1, 1, 0] card.
      Build any 1 card. Play top.

    _foundation_
      Pile 8 horz N. Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: SS_RowStack (base_rank=KING)
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=513, name='Ocean Towers', game_type=(GT.FREECELL |
                    GT.OPEN | GT.ORIGINAL), decks=2,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FortyThievesLayout.FortyThievesLayout
    _row_ = Wrap(stack.SuperMoveSS_RowStack, base_rank=cs.KING)

    def _create_game(self, **kw):
        kwdefault(kw, rows=14, reserves=8, playcards=20)
        super(OceanTowers, self)._create_game(**kw)

    def _start(self, rows=7, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~7 ea.
          - s[reserves][1:-1] 1 ea.

        .. \_start(rows=7) -> None
        """
        super(Clink, self)._start(rows=7, **kw)
        self.s['talon'].dealRow(rows=self.s['reserves'][1:-1])


class Headquarters(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.fortythieves.FortyThievesLayout
        - reserve [6 horz S foundation, no offset]
        - row [8 horz S reserve, vert offset]
        - talon [1 SE, no offset]
        - waste [1 W talon, no offset]
        - foundation [8 horz NE, no offset]

    _row_
      Init deal 13 open card. Build
      down in rank by alt color. Play seq. Base none.

    _reserve_
      Build any 1 seq. Play seq.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack (base_rank=GAP)
    :cvar Stack _reserve_: SequenceReserve (max_cards=MAX, max_accept=MAX,
      max_move=MAX)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=648, name='Headquarters', game_type=(GT.FREECELL |
                    GT.OPEN | GT.ORIGINAL), decks=2,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FortyThievesLayout.FortyThievesLayout
    _row_ = Wrap(stack.AC_RowStack, base_rank=cs.GAP)
    _reserve_ = Wrap(SequenceReserve, max_cards=cs.MAX,
                             max_accept=cs.MAX, max_move=cs.MAX)

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, reserves=6, playcards=16,
                  align=layout.LEFT)
        return super(Headquarters, self)._create_game(**kw)

    def _start(self, rows=13, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~13 ea.

        .. \_start(rows=13) -> None
        """
        return super(Headquarters, self)._start(rows=13, **kw)


class CanCan(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [13 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [3 horz NW, no offset]

    _row_
      Init deal 3 open card then
      after _reserve_ init deal cards on 1st nine. Build down in rank by alt
      color. Play seq. Base KING.

    _reserve_
      Init deal 1 card. Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack (base_rank=KING)
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=698, name='Can Can', game_type=(GT.RAGLAN | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL,
                    version='1.00fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(stack.AC_RowStack, base_rank=cs.KING)
    _reserve_ = Wrap(stack.OpenStack, max_accept=0)
    _hint_ = DefaultHint

    def _create_game(self, **kw):
        kwdefault(kw, rows=13, reserves=3, playcards=20)
        super(CanCan, self)._create_game(**kw)

    def _start(self, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~4 ea.
          - s[reserves] 1 ea.

        .. \_start(rows=4) -> None
        """
        super(CanCan, self)._start(rows=rows - 1, *kw)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRowAvail()


class Limpopo(FreeCell):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [8 over 2 row NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal 13 open card. Build
      down in rank by alt color. Play seq.

    _reserve_
      Build any 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=746, name='Limpopo', game_type=(GT.FREECELL |
                    GT.ORIGINAL), decks=2,
                    skill_level=SL.MOSTLY_SKILL, version='1.10fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = stack.AC_RowStack

    def _create_game(self, **kw):
        kw.setdefault('reserves', 2)
        super(Limpopo, self)._create_game(**kw)

    def _start(self, rows=13, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~13 ea.

        .. \_start(rows=13) -> None
        """
        super(Limpopo, self)._start(rows=rows, **kw)


PROVIDES = [RelaxedFreeCell, FreeCell, ForeCell, Stalactites, DoubleFreecell,
            TripleFreecell, ChallengeFreeCell, SuperChallengeFreeCell,
            Spidercells, SevenByFour, SevenByFive, Bath, Clink, Repair,
            Cell11, FourColours, BigCell, OceanTowers, GermanFreeCell,
            KingCell, Headquarters, CanCan, Limpopo]